home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************************
- #
- # displays.c
- #
- # This segment handles the Display Manager notification and
- # repositions application windows in response.
- #
- # Author(s): Michael Marinkovich
- # Apple Developer Technical Support
- # marink@apple.com
- #
- # Modification History:
- #
- # 4/3/96 MWM Initial coding
- #
- # Copyright © 1992-96 Apple Computer, Inc., All Rights Reserved
- #
- #
- # You may incorporate this sample code into your applications without
- # restriction, though the sample code has been provided "AS IS" and the
- # responsibility for its operation is 100% yours. However, what you are
- # not permitted to do is to redistribute the source as "DSC Sample Code"
- # after having made changes. If you're going to re-distribute the source,
- # we require that you make it clear in the source that the code was
- # descended from Apple Sample Code, but that you've made changes.
- #
- *************************************************************************************/
-
- #include <Events.h>
- #include <ToolUtils.h>
- #include <Gestalt.h>
- #include <OSUtils.h>
-
-
- #include "App.h"
- #include "Proto.h"
-
-
- //----------------------------------------------------------------------
- // Globals
- //----------------------------------------------------------------------
-
- DMNotificationUPP gDMNUPP;
- ProcessSerialNumber gThePSN;
-
-
- //----------------------------------------------------------------------
- //
- // InstallDMNotification - tell DM that we want to be notified by callback.
- //
- //
- //----------------------------------------------------------------------
-
- OSErr InstallDMNotification(void)
- {
- OSErr err;
-
- // use our process number so when we get called
- // the A5 is ours
- err = GetCurrentProcess(&gThePSN);
-
- if (err == noErr)
- {
- gDMNUPP = NewDMNotificationProc(WorldChangedProc);
- err = DMRegisterNotifyProc(gDMNUPP, &gThePSN);
- }
-
- return err;
-
- }
-
-
- //----------------------------------------------------------------------
- //
- // InstallAEDMNotification - tell DM that we want to be notified by AE.
- //
- //
- //----------------------------------------------------------------------
-
- OSErr InstallAEDMNotification(void)
- {
- OSErr err;
-
- err = AEInstallEventHandler(kCoreEventClass, kAESystemConfigNotice,
- NewAEEventHandlerProc(DoAEDisplayUpdate),
- 0L, false);
-
- return err;
-
- }
-
-
- //----------------------------------------------------------------------
- //
- // RemoveDMNotification - tell DM that we no longer want to be notified.
- //
- //
- //----------------------------------------------------------------------
-
- OSErr RemoveDMNotification(void)
- {
- OSErr err;
-
- err = DMRemoveNotifyProc(gDMNUPP, &gThePSN);
-
- return err;
-
- }
-
-
- //----------------------------------------------------------------------
- //
- // WorldChangedProc - Display Manager calls this proc when a depth or
- // mode change is made. Your application should
- // handle window repositioning here.
- //----------------------------------------------------------------------
-
- pascal OSErr WorldChangedProc(AppleEvent *event)
- {
- OSErr err;
-
- err = HandleNotification(event);
-
- return noErr;
-
- }
-
-
- //----------------------------------------------------------------------
- //
- // DoAEDisplayUpdate - Display Manager calls this proc when a depth or
- // mode change is made. Your application should
- // handle window repositioning here.
- //----------------------------------------------------------------------
-
- pascal OSErr DoAEDisplayUpdate(AppleEvent event,AppleEvent reply,long refCon)
- {
- OSErr err;
-
- err = HandleNotification(&event);
-
- return noErr;
-
- }
-
-
- //----------------------------------------------------------------------
- //
- // HandleNotification - handle the AppleEvent returned by either the
- // callback or the AppleEvent procedure.
- //
- //----------------------------------------------------------------------
-
- OSErr HandleNotification(AppleEvent *event)
- {
- OSErr err;
- GrafPtr oldPort;
- AEDescList displayList;
- AEDescList aDisplay;
- AERecord oldConfig,newConfig;
- AEKeyword tempWord;
- DisplayIDType displayID;
- unsigned long returnType;
- long count;
- Rect oldRect, newRect;
-
- GetPort(&oldPort);
-
- // Get a list of the displays from the Display Notice AppleEvent.
- err = AEGetParamDesc(event,kAEDisplayNotice,typeWildCard,&displayList);
- // How many items in the list
- err = AECountItems(&displayList,&count);
-
- while (count > 0) // Loop through the list.
- {
- err = AEGetNthDesc(&displayList, count, typeWildCard, &tempWord,
- &aDisplay);
-
- // Get the Old Rect.
- err = AEGetNthDesc(&aDisplay, 1, typeWildCard, &tempWord,
- &oldConfig);
- err = AEGetKeyPtr(&oldConfig, keyDeviceRect, typeWildCard,
- &returnType, &oldRect, 8, nil);
-
- // Get the DisplayID so we can get the GDevice later.
- err = AEGetKeyPtr(&oldConfig, keyDisplayID, typeWildCard,
- &returnType, &displayID, 8, nil);
-
- // Get the New Rect.
- err = AEGetNthDesc(&aDisplay, 2, typeWildCard, &tempWord,
- &newConfig);
- err = AEGetKeyPtr(&newConfig, keyDeviceRect, typeWildCard,
- &returnType, &newRect, 8, nil);
-
- // If the New and Old rects are not the same then we can assume
- // the GDevice has changed and we need to rearrange the windows.
- if (err == noErr && !EqualRect(&newRect, &oldRect))
- HandleDeviceChange(displayID, &newRect);
-
- count--;
- err = AEDisposeDesc(&aDisplay);
- err = AEDisposeDesc(&oldConfig);
- err = AEDisposeDesc(&newConfig);
-
- }
-
- err = AEDisposeDesc(&displayList);
- SetPort(oldPort);
-
- return err;
-
- }
-
-
- //----------------------------------------------------------------------
- //
- // HandleDeviceChange - called when the oldconfig is different from
- // newconfig. Will check all windows on effected
- // device and move if needed.
- //----------------------------------------------------------------------
-
- OSErr HandleDeviceChange(DisplayIDType displayID, Rect *newRect)
- {
- OSErr err = noErr;
- GDHandle gd;
- GDHandle onGD;
- WindowRef window;
-
- // Get the GDevice from the DisplayID.
- err = DMGetGDeviceByDisplayID((DisplayIDType) displayID, &gd, false);
-
- if (err == noErr && gd != nil)
- {
- window = FrontWindow();
-
- while (window != nil)
- {
- SetPort(window);
- // which device holds the greatest portion of the window
- onGD = GetGreatestDevice(window);
-
- // If the window is not 50% or greater on
- // the desired device then pass it up.
- if (onGD == gd)
- {
- if (OutOfBoundsRect(gd, window, *newRect))
- {
- MoveInbounds(window, gd, *newRect);
- if (OutOfBoundsRect(gd, window, *newRect))
- {
- ResizeInbounds(window, gd, *newRect);
-
- // If it is one of our document windows then we need
- // to reset the std state and the scroll bars.
- if (GetIsAppWindow(window))
- AdjustScrollbars(window, true);
- }
- }
- ResetStdState(window);
-
- }
- window = (WindowRef)(((WindowPeek)window)->nextWindow);
- }
- }
-
- return err;
-
- }
-
-
- //----------------------------------------------------------------------
- //
- // OutOfBoundsRect - check to see if the window is out of the device
- // rect.
- //
- //----------------------------------------------------------------------
-
- Boolean OutOfBoundsRect(GDHandle gd, WindowRef window, Rect screenRect)
- {
- Boolean out = false;
- Rect windRect;
- short mHeight = 0;
-
- GetWindowRect(window, &windRect);
-
- if (gd == GetMainDevice())
- mHeight = GetMBarHeight();
-
- if ((windRect.right > screenRect.right) || (windRect.bottom > screenRect.bottom))
- out = true;
-
- if ((windRect.left < screenRect.left) || (windRect.top < screenRect.top + mHeight))
- out = true;
-
- return out;
-
- }
-
-
- //----------------------------------------------------------------------
- //
- // MoveInbounds - Move window on to desired device
- //
- //
- //----------------------------------------------------------------------
-
- void MoveInbounds(WindowRef window, GDHandle gd, Rect screenRect)
- {
- Rect bounds;
- short mHeight = 0;
- short hGlobal;
- short vGlobal;
-
- GetWindowRect(window, &bounds);
-
- if (gd == GetMainDevice())
- mHeight = GetMBarHeight();
-
- hGlobal = bounds.left;
- vGlobal = bounds.top + kTitleBarHeight;
-
- // we want to make the left-top a priority so adjust it first
- // as to override the bottom, right movements. This is so we
- // can resize the window later.
-
- if (((bounds.right - bounds.left) > (screenRect.right - screenRect.left)) ||
- ((bounds.bottom - bounds.top) >
- ((screenRect.bottom - screenRect.top) - mHeight)))
- {
-
- // adjust left
- if (bounds.left < screenRect.left)
- hGlobal = screenRect.left + kFudgeFactor;
-
- // adjust top
- if (bounds.top < screenRect.top + mHeight)
- vGlobal = screenRect.top + kTitleBarHeight + mHeight + kFudgeFactor;
-
- }
- else
- {
- // adjust left
- if (bounds.left < screenRect.left)
- hGlobal = screenRect.left + kFudgeFactor;
- else
- {
- // adjust right
- if (bounds.right > screenRect.right)
- hGlobal = (screenRect.right - (bounds.right - bounds.left)) - kFudgeFactor;
- }
-
- // adjust top
- if (bounds.top < screenRect.top + mHeight)
- vGlobal = screenRect.top + kTitleBarHeight + mHeight + kFudgeFactor;
-
- else
- {
- // adjust bottom
- if (bounds.bottom > screenRect.bottom)
- vGlobal = (screenRect.bottom - kFudgeFactor -
- (bounds.bottom - bounds.top) + mHeight);
- }
-
- }
-
- MoveWindow(window, hGlobal, vGlobal,false);
-
- }
-
-
- //----------------------------------------------------------------------
- //
- // ResizeInbounds - resize the window to fit in the graphics device
- //
- //
- //----------------------------------------------------------------------
-
- void ResizeInbounds(WindowRef window, GDHandle gd, Rect screenRect)
- {
- Rect windRect;
- short h;
- short v;
-
- windRect = window->portRect;
- // make the window bounds the size of the gdRect
- // less the fudge factor.
- h = windRect.right - windRect.left;
- v = windRect.bottom - windRect.top;
-
- if (h > screenRect.right - screenRect.left)
- h = ((screenRect.right - screenRect.left) - (kFudgeFactor * 2));
-
- if (v > screenRect.bottom - screenRect.top)
- {
- v = ((screenRect.bottom - screenRect.top) - (kFudgeFactor * 2));
-
- // If we are on the main device then subtract the mBar
- // height plus a fudge factor for a boundary.
- if (gd == GetMainDevice())
- v -= (GetMBarHeight() + kTitleBarHeight);
- }
-
-
- SizeWindow(window, h, v, true);
-
- }
-
-
- //----------------------------------------------------------------------
- //
- // GetGreatestDevice - find thw device that holds the greatest area
- // of the window.
- //
- //----------------------------------------------------------------------
-
- GDHandle GetGreatestDevice(WindowRef window)
- {
- GDHandle gd;
- GDHandle savedGD;
- Rect gdRect;
- Rect foundRect;
- long size;
- long greatest = nil;
-
- gd = DMGetFirstScreenDevice(dmOnlyActiveDisplays);
- savedGD = gd;
-
- // Loop through the device list
- while (gd != nil)
- {
- gdRect = (**gd).gdRect;
-
- GlobalToLocal(&topLeft(gdRect));
- GlobalToLocal(&botRight(gdRect));
-
- if (SectRect(&window->portRect, &gdRect, &foundRect))
- {
- size = ((long)(foundRect.right - foundRect.left) *
- (long)(foundRect.bottom - foundRect.top));
-
- if (size > greatest)
- {
- greatest = size;
- savedGD = gd; // save the greatest device
- }
- }
- gd = DMGetNextScreenDevice(gd, dmOnlyActiveDisplays);
- }
-
- return savedGD;
-
- }
-
-
- //----------------------------------------------------------------------
- //
- // GetWindowRect - return actual window rect in global coords
- //
- //
- //----------------------------------------------------------------------
-
- void GetWindowRect(WindowRef window, Rect *windRect)
- {
- *windRect = window->portRect;
-
- // add the titlebar height for actual height
- windRect->top -= kTitleBarHeight;
-
- LocalToGlobal(&TopLeft(*windRect));
- LocalToGlobal(&BotRight(*windRect));
-
-
- }
-
- //----------------------------------------------------------------------
- //
- // ResetStdState - since we are now on a different size screen we need
- // to change the stdState window size so our zooming
- // will work properly.
- //----------------------------------------------------------------------
-
- void ResetStdState(WindowRef window)
- {
- Rect screenRect;
-
- screenRect = window->portRect;
-
- LocalToGlobal(&TopLeft(screenRect));
- LocalToGlobal(&BotRight(screenRect));
-
- // with the new interfaces we could also use the
- // SetWindowStandardState procedure.
- (**(WStateDataHandle)
- ((WindowPeek)window)->dataHandle).stdState = screenRect;
-
-
- }
-
-
-
-
-
-
-